/***********************************************************************
 * Title: des.sc
 * Author: Brian Peck
 * Date: Spring 2011
 * Description: Specification model for DES module
 ***********************************************************************/

import "i_sender";
import "i_receiver";
import "des.h";

behavior des(i_receiver ir, i_sender is)
{
  void main(void) {
    unsigned long fval, work, right leftt;
    int round;
    unsigned long *block, keys;
    while(1) {
      // get info
      ir.receive(&block, sizeof(block));
      ir.receive(&keys, sizeof(keys));

      // Do DES
      leftt = block[0];
      right = block[1];
      work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
      right ^= work;
      leftt ^= (work << 4);
      work = ((leftt >> 16) ^ right) & 0x0000ffffL;
      right ^= work;
      leftt ^= (work << 16);
      work = ((right >> 2) ^ leftt) & 0x33333333L;
      leftt ^= work;
      right ^= (work << 2);
      work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
      leftt ^= work;
      right ^= (work << 8);
      right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
      work = (leftt ^ right) & 0xaaaaaaaaL;
      leftt ^= work;
      right ^= work;
      leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;

      for( round = 0; round < 8; round++ ) {
        work  = (right << 28) | (right >> 4);
        work ^= *keys++;
        fval  = SP7[ work        & 0x3fL];
        fval |= SP5[(work >>  8) & 0x3fL];
        fval |= SP3[(work >> 16) & 0x3fL];
        fval |= SP1[(work >> 24) & 0x3fL];
        work  = right ^ *keys++;
        fval |= SP8[ work        & 0x3fL];
        fval |= SP6[(work >>  8) & 0x3fL];
        fval |= SP4[(work >> 16) & 0x3fL];
        fval |= SP2[(work >> 24) & 0x3fL];
        leftt ^= fval;
        work  = (leftt << 28) | (leftt >> 4);
        work ^= *keys++;
        fval  = SP7[ work        & 0x3fL];
        fval |= SP5[(work >>  8) & 0x3fL];
        fval |= SP3[(work >> 16) & 0x3fL];
        fval |= SP1[(work >> 24) & 0x3fL];
        work  = leftt ^ *keys++;
        fval |= SP8[ work        & 0x3fL];
        fval |= SP6[(work >>  8) & 0x3fL];
        fval |= SP4[(work >> 16) & 0x3fL];
        fval |= SP2[(work >> 24) & 0x3fL];
        right ^= fval;
      } // end for

      right = (right << 31) | (right >> 1);
      work = (leftt ^ right) & 0xaaaaaaaaL;
      leftt ^= work;
      right ^= work;
      leftt = (leftt << 31) | (leftt >> 1);
      work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
      right ^= work;
      leftt ^= (work << 8);
      work = ((leftt >> 2) ^ right) & 0x33333333L;
      right ^= work;
      leftt ^= (work << 2);
      work = ((right >> 16) ^ leftt) & 0x0000ffffL;
      leftt ^= work;
      right ^= (work << 16);
      work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
      leftt ^= work;
      right ^= (work << 4);
      *block++ = right;
      *block = leftt;

      is.send(&block, sizeof(block));
    } // end while
  } // end main
} // end behavior des

